Add net9 File.WriteAllBytes over a span - #606
Merged
Merged
Conversation
One member. Diffing the whole byte writing family showed the rest was already covered: AppendAllBytes in both forms, both AppendAllBytesAsync overloads, both WriteAllBytesAsync overloads and ReadAllBytesAsync are all polyfilled already. WriteAllBytes(string, ReadOnlySpan<byte>) was the only gap. Verified against net11 that the span overload is indistinguishable from the array overload: identical content for empty, small and 100KB payloads, the same truncation of a longer existing file, the same creation of a missing one, and the same exception for a null, empty or whitespace path, a missing directory and a path that is a directory. So the polyfill delegates to the array overload rather than opening its own FileStream, which would have meant guessing at the file mode and sharing. Also fixes the //Link: on the existing WriteAllBytesAsync(string, ReadOnlyMemory<byte>, CancellationToken), which pointed at AppendAllBytesAsync. API count 1161 -> 1162.
This was referenced Sep 10, 2026
This was referenced Sep 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
One member —
File.WriteAllBytes(string, ReadOnlySpan<byte>).Most of this family was already done
Diffing the whole byte-writing surface of
Fileacross the reference assemblies turned up eight members missing below net9, and seven of them are already polyfilled:AppendAllBytesin both the array and span forms, bothAppendAllBytesAsyncoverloads, bothWriteAllBytesAsyncoverloads, andReadAllBytesAsync.WriteAllBytes(string, ReadOnlySpan<byte>)was the only real gap.Delegating to the array overload, deliberately
The neighbouring polyfills in this file open their own
FileStream(FileMode.Create,FileShare.None, and so on). This one does not, because it does not have to:File.WriteAllBytes(path, bytes.ToArray())inherits the BCL's own file mode, sharing and validation rather than my guess at them.Verified against net11 that the span overload really is indistinguishable from the array overload:
null, empty or whitespace path, a missing directory, and a path that is a directorySo the delegation is faithful, and the cost is the array copy, which is
//Note:d along with the fact that it is only reached with an explicitReadOnlySpan— abyte[]argument binds to the BCL overload, as it does today.A .NET Framework difference the tests had to accommodate
My first version pinned the empty-path failure as
ArgumentException:path. That passed everywhere except net462, whereFile.WriteAllBytes("", bytes)throwsArgumentExceptionwith no paramName, while .NET names itpath. That is a BCL difference between frameworks, and the polyfill correctly inherits whichever the running framework has — the equivalence assertion against the array overload passed on net462 all along; only my Core-specific hard-coded expectation failed.The tests now assert full equivalence with the array overload on every framework, and pin concrete shapes only where they are stable everywhere (
ArgumentNullException:path,DirectoryNotFoundException), checking just the exception type for the empty and whitespace cases. The comment records why.Also fixed
The existing
WriteAllBytesAsync(string, ReadOnlyMemory<byte>, CancellationToken)carried a//Link:pointing atappendallbytesasync. Corrected.Verification
Solution clean in Release, Consume clean across all 22 TFMs, tests green on net11.0 (1745), net10.0 (1745), net9.0 (1745), net8.0 (1742), net462 (1691), plus PublicTests, EmbeddedTests, UnsafeTests, NoRefsTests and NoExtrasTests.
API count 1161 → 1162.